﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using InnovTech.Persistence;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Linq;

namespace InnovTech.Persistence
{
    public class NHDao : IDao
    {
        ISession _session;
        public NHDao(ISession sess)
        {
            _session = sess;
        }

        public void Save(params object[] toSaveList)
        {
            if (toSaveList == null) return;
            foreach(object obj in toSaveList)
                _session.SaveOrUpdate(obj);
            _session.Flush();
        }

        public void Delete(params object[] toDeleteList)
        {
            if (toDeleteList == null) return;
            foreach (object obj in toDeleteList)
                _session.Delete(obj);
            _session.Flush();
        }

        public T Get<T>(object id)
        {
            return _session.Get<T>(id);
        }

        public IEnumerable<T> List<T>(Func<T, bool> predicate)
        {
            return _session.Query<T>().ToFuture().Where(t => predicate(t));
        }

        public void Dispose()
        {
            if (_session != null)
            {
                if (_session.IsOpen)
                    _session.Close();
                _session.Dispose();
            }
        }
    }

    public class NHibernateDao<TEntity, TID> : IDao<TEntity, TID>, IDisposable
        where TEntity : IEntity<TID>
    {
        protected virtual void ValidateSession(ISession session)
        {
            if (session == null)
                throw new ArgumentNullException("The given ISession instance can not be null");
            if (!session.IsOpen)
                throw new InvalidOperationException("The given ISession instance is not open");
        }

        ISession _session;
        public NHibernateDao(ISession sess)
        {
            ValidateSession(sess);
            _session = sess;
        }

        public void Save(params TEntity[] toSaveList)
        {
            if (toSaveList == null) return;
            foreach (object obj in toSaveList)
                _session.SaveOrUpdate(obj);
            _session.Flush();
        }

        public void Delete(params TEntity[] toDeleteList)
        {
            if (toDeleteList == null) return;
            foreach (object obj in toDeleteList)
                _session.Delete(obj);
            _session.Flush();
        }

        public TEntity Get(TID id)
        {
            return _session.Get<TEntity>(id);
        }

        public IEnumerable<TEntity> List(Func<TEntity, bool> predicate)
        {
            return _session.Query<TEntity>().ToFuture().Where(t => predicate(t));
        }

        public void Dispose()
        {
            if (_session != null)
            {
                if (_session.IsOpen)
                    _session.Close();
                _session.Dispose();
            }
        }
    }

}
